﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using FlowBasis.Data;
using FlowBasis.Security.Passwords;
using FlowBasisSampleSite.Domain.Entities;
using System.Security.Cryptography;
using System.Text;

namespace FlowBasisSampleSite.Lib.Security
{
    public class PasswordResetService
    {
        private const int DefaultPasswordLength = 10;

        private Func<IUnitOfWork> unitOfWorkFactory;
        private IHashedPasswordValidationService passwordValdiationService;

        public PasswordResetService(Func<IUnitOfWork> unitOfWorkFactory, IHashedPasswordValidationService passwordValdiationService)
        {
            this.unitOfWorkFactory = unitOfWorkFactory;
            this.passwordValdiationService = passwordValdiationService;
        }

        public void ResetPasswordForEmailAddress(string email)
        {
            var unitOfWork = this.unitOfWorkFactory();

            var userAccount = unitOfWork.GetAll<UserAccount>().SingleOrDefault(ua => ua.PrimaryEmail == email);
            if (userAccount != null)
            {
                string newPassword = this.GenerateRandomPassword(DefaultPasswordLength);
                byte[] salt = this.passwordValdiationService.GenerateSalt(32);
                byte[] hash = this.passwordValdiationService.ComputeHash(newPassword, salt);

                userAccount.PasswordHash = hash;
                userAccount.PasswordSalt = salt;

                unitOfWork.Commit();

                // TODO: Send message indicating that email has been reset.
            }            
        }

        public string GenerateRandomPassword(int passwordLength)
        {
            string possibleCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";

            byte[] randomBytes = new byte[passwordLength];
            using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
            {
                rng.GetBytes(randomBytes);
            }

            var sb = new StringBuilder();
            for (int co = 0; co < randomBytes.Length; co++)
            {
                char ch = possibleCharacters[randomBytes[co] % possibleCharacters.Length];
                sb.Append(ch);
            }

            return sb.ToString();
        }
    }
}